package com.lemzdo.community.service.impl;

import com.lemzdo.community.dto.PostDTO;
import com.lemzdo.community.exception.CustomizeException;
import com.lemzdo.community.exception.ErrCodeEnum;
import com.lemzdo.community.mapper.PostMapper;
import com.lemzdo.community.mapper.UserMapper;
import com.lemzdo.community.model.Post;
import com.lemzdo.community.model.PostExample;
import com.lemzdo.community.model.User;
import com.lemzdo.community.service.PostService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private PostMapper postMapper;
    @Autowired
    private UserMapper userMapper;


    @Override
    public int deleteByPrimaryKey(Integer id) {
        return postMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(Post record) {
        return postMapper.insert(record);
    }

    @Override
    public int insertSelective(Post record) {
        return postMapper.insertSelective(record);
    }

    /**
     * 根据post的id查询对应的帖子信息和对应的user的信息
     * @param id 帖子id
     * @return postDTO
     */
    @Override
    public PostDTO selectByPrimaryKey(Integer id) {
        //新建一个postDTO用于返回 存放id对应的post内容和对应的user内容
        PostDTO postDTO = new PostDTO();
        //取得post内容
        Post post = postMapper.selectByPrimaryKey(id);
        //判断post是否有内容
        if(post==null){
            //直接传递具体枚举
            throw new CustomizeException(ErrCodeEnum.POST_NOT_FOUND);
        }
        //复制放入postDTO中
        BeanUtils.copyProperties(post,postDTO);
        //取出对应的user内容
        User user = userMapper.selectByPrimaryKey(post.getAuthorId());
        //user放入dto中
        postDTO.setUser(user);

        return postDTO;
    }

    @Override
    public int updateByPrimaryKeySelective(Post record) {
        return postMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(Post record) {
        return postMapper.updateByPrimaryKey(record);
    }

    /**
     * 查询post数据库中所有的数据(根据搜索的msg)，并根据作者id关联到user表，查询出user表中的头像，
     * 一起存入postDTO中，方便返回给前端页面
     * @return PostDTO（post表的数据外加对应的用户头像）
     */
    @Override
    public List<PostDTO> selectAllPostDTO(String searchMsg) {


        //定义一个postList用来存放 所有post 或者 带搜索条件的post
        List<Post> postList = new ArrayList<>();

        if(StringUtils.isNotBlank(searchMsg)){
            //搜索内容不为空 表示根据搜索模糊查询出需要的帖子
            //根据共空格分割出搜索条件
            String[] messages = searchMsg.split(" ");

            //取得帖子表中的信息（根据搜索msg 标题模糊查询）
            PostExample example = new PostExample();
            PostExample.Criteria criteria = example.createCriteria();
            //遍历各个搜索条件，模糊查询出结果
            for (String message : messages) {
                criteria.andTitleLike("%" + message + "%");
            }
            postList = postMapper.selectByExample(example);

        }else {

            //搜索内容为空 表示直接查询出所有的帖子
            //取得帖子表中的信息
            PostExample example = new PostExample();
             postList = postMapper.selectByExample(example);
        }


        //遍历postList 将其中每个作者id对应user的id，取出头像存入DTO
        List<PostDTO> postDTOList = new ArrayList<>();
        for (Post post : postList) {
            //关联id，获得user
            User user = userMapper.selectByPrimaryKey(post.getAuthorId());
            //将post中所有的数据外加user，一起存入DTO中(主要需要user头像)
            //可以一个一个SET，也可以spring内置工具BeanUtils
            PostDTO postDTO = new PostDTO();//新建postDto
            BeanUtils.copyProperties(post,postDTO);//post数据复制到postDTO中，根据名字一一对应
            postDTO.setUser(user);//将作者id对应的user放入dto中
            //将遍历的这个postDTO放入list中
            postDTOList.add(postDTO);
        }
        return postDTOList;
    }

    /**
     *  查询帖子数量 以供手写的pageHelper使用（分有搜索内容和无搜索内容情况）
     * @param searchMsg 传递过来的搜索信息
     * @return 帖子数量
     */
    @Override
    public Integer count(String searchMsg) {
        if(StringUtils.isNotBlank(searchMsg)){
            //搜索内容不为空 表示根据搜索查询出需要的帖子数量
            String[] messages = searchMsg.split(" ");

            //取得帖子表中的信息（根据搜索msg 标题模糊查询）
            PostExample example = new PostExample();
            PostExample.Criteria criteria = example.createCriteria();
            //遍历各个搜索条件，模糊查询出结果
            for (String message : messages) {
                criteria.andTitleLike("%" + message + "%");
            }
            return Math.toIntExact(postMapper.countByExample(example));
        }
        //搜索内容为空 表示查询出所有的帖子数量
        PostExample example = new PostExample();
        return Math.toIntExact(postMapper.countByExample(example));
    }

    @Override
    public List<Post> selectAllByAuthorId(Integer authorId) {

        PostExample example = new PostExample();
        example.createCriteria().andAuthorIdEqualTo(authorId);
        return postMapper.selectByExample(example);

    }

    /**
     * 根据作者id查询帖子数量
     * @return 数量
     */
    @Override
    public Integer countByAuthorId(Integer authorId) {
        PostExample example = new PostExample();
        example.createCriteria().andAuthorIdEqualTo(authorId);

        return Math.toIntExact(postMapper.countByExample(example));
    }

    /**
     * 根据帖子的id去数据库对比，存在即修改帖子，不存在即插入帖子（发布）
     * @param post 帖子信息
     */
    @Override
    public void createOrUpdate(Post post) {
        //根据新帖子的id去数据库中查询数据
        Post dbPost = postMapper.selectByPrimaryKey(post.getId());
        if(dbPost==null){
            //数据库中没有，插入数据（发布）
            // controller中没有获取创建时间 数据库中有值就不用修改时间 所以插入的时候设置
            post.setGmtCreate(System.currentTimeMillis());
            post.setGmtModified(post.getGmtCreate());
            postMapper.insertSelective(post);

        }else {
            //数据库中存在，修改数据（更新） 不用更新创建时间
            int updateNum = postMapper.updateByPrimaryKeySelective(post);
            //需要判断更新帖子的时候，是否还存在 避免更新时，作者在其他页面删除了帖子
            if(updateNum!=1){
                throw new CustomizeException(ErrCodeEnum.POST_NOT_FOUND);
            }
        }

    }

    /**
     * 根据id进行浏览数增加
     *  Post post = postMapper.selectByPrimaryKey(id);
     *  post.setViewCount(post.getViewCount()+1);
     *  postMapper.updateByPrimaryKeySelective(post)；
     * 会有并发问题，例如：4个人访问同一个帖子，get的浏览量都是15 都访问
     *  最后一个人更新后 会变成16  实际情况应该是19
     *  需要自定义一个sql语句，viewCount=viewCount+1
     * @param id 帖子id
     */
    @Override
    public void increaseView(Integer id) {
       /* //取得对应的帖子
        Post post = postMapper.selectByPrimaryKey(id);
        //浏览量+1
        post.setViewCount(post.getViewCount()+1);
        //更新新的浏览量
        postMapper.updateByPrimaryKeySelective(post);*/
        //自定义的sql语句
        // update post set (view_count = view_count+1) where id = #{id,jdbcType=INTEGER}
        postMapper.increaseView(id);

    }

    /**
     * 根据id进行评论数增加
     * 等同于上面的根据id进行浏览数增加
     * @param id 帖子id
     */
    @Override
    public void increaseComment(Integer id) {
        postMapper.increaseComment(id);
    }

    /**
     * 根据原贴信息（id，标签），查询出相关的帖子信息 显示在右边，不包括原贴
     * @param postDTO 原贴信息（标签）
     * @return 相关的帖子信息
     */
    @Override
    //public List<PostDTO> selectAllRelated(PostDTO postDTO) {
    //无需原贴信息 所以改成<Post>
    public List<Post> selectAllRelated(PostDTO postDTO) {
        //标签可以为空，所以需要判断
        if(StringUtils.isBlank(postDTO.getTag())){
            //标签为空 返回一个空list
            return new ArrayList<>();
        }

        //根据逗号分割出每一个标签
        String[] tags = StringUtils.split(postDTO.getTag(), ",");

        //List<PostDTO> postDTOList = new ArrayList<>();
        List<Post> postList = new ArrayList<>();

        //遍历标签 每个标签模糊查询出posts
        for (String tag : tags) {
            PostExample example = new PostExample();
            PostExample.Criteria criteria = example.createCriteria();
            //标签模糊查询
            criteria.andTagLike("%" + tag + "%");
            //去掉原贴
            criteria.andIdNotEqualTo(postDTO.getId());
            //赋值给postList
            postList.addAll(postMapper.selectByExample(example));

            //遍历posts 给每个post加user信息 赋值给postDTO
            /*for (Post post : postList) {
                PostDTO postDTOTemp = new PostDTO();
                BeanUtils.copyProperties(post,postDTOTemp);
                User user = userMapper.selectByPrimaryKey(post.getAuthorId());
                postDTOTemp.setUser(user);
                postDTOList.add(postDTOTemp);

            }*/
        }

        //一个标签会模糊查询出多个post，需要去重(使用java8新特性函数去重)
        //return postDTOList.stream().distinct().collect(Collectors.toList());

        return postList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 根据post id查询post信息
     * @param postId 帖子id
     * @return post信息
     */
    @Override
    public Post getPostById(Integer postId) {
        return postMapper.selectByPrimaryKey(postId);
    }


}
